package com.swak.persistence.mybatis.methods.impls;

import com.swak.define.ColumnDefine;
import com.swak.persistence.mybatis.methods.AbstractMethod;
import com.swak.persistence.mybatis.methods.Sqls;
import com.swak.utils.StringUtils;

public class Merge extends AbstractMethod {

	@Override
	protected void doInject() {
		if (!this.supportMethod(Sqls.MERGE)) {
			return;
		}

		String sql = new StringBuilder().append(SCRIPT_START).append(this.parseSql()).append(SCRIPT_END).toString();

		this.addInsertMappedStatement(this.table.entity, Sqls.MERGE.getMethod(), sql);
	}

	protected String parseSql() {
		StringBuilder sql = new StringBuilder();
		sql.append(this.withMergeUpdateFlagHintClause()).append(this.parsePureUpdateProperty()).append(IF_END);
		sql.append(this.withoutMergeUpdateFlagHintClause()).append(this.parseReplaceProperty()).append(IF_END);
		return sql.toString();
	}

	protected String withMergeUpdateFlagHintClause() {
		return StringUtils.format("<if test=\" %s != null and %s != null \">", Hint, Hint_MergeUpdateFlag);
	}

	protected String withoutMergeUpdateFlagHintClause() {
		return StringUtils.format("<if test=\" %s == null or %s == null \">", Hint, Hint_MergeUpdateFlag);
	}

	protected String parsePureUpdateProperty() {
		return new StringBuilder().append(UPDATE).append(SPACE).append(this.table.getName()).append(SPACE)
				.append(this.convertSet(this.parseUpdateProperty())).append(SPACE).append(WHERE).append(SPACE)
				.append(this.parsePkEqualColumns()).toString();
	}

	protected String convertSet(String sql) {
		return SET_START + sql + SET_END;
	}

	protected String parseReplaceProperty() {
		return new StringBuilder().append(INSERT).append(SPACE).append(this.table.getName()).append(LEFT_BRACKET)
				.append(this.parseSqlColumns()).append(RIGHT_BRACKET).append(SPACE).append(VALUES).append(LEFT_BRACKET)
				.append(this.parseInsertSqlProperty()).append(RIGHT_BRACKET).append(SPACE).append(REPLACE).append(SPACE)
				.append(UPDATE).append(SPACE).append(this.parseUpdateProperty()).toString();
	}

	/**
	 * 解析列
	 */
	@Override
	protected String parseSqlColumns() {
		StringBuilder sql = new StringBuilder();
		for (ColumnDefine column : table.columns) {
			String name = column.name;
			sql.append(name).append(SPLIT);
		}
		if (table.define.useLogicDel()) {
			sql.append(DEL_AT);
		} else {
			sql.delete(sql.lastIndexOf(SPLIT), sql.length() - 1);
		}
		return sql.toString();
	}

	/**
	 * insert 后面的属性值
	 * 
	 * @param <T>
	 * @param table
	 * @return
	 */
	protected String parseInsertSqlProperty() {
		StringBuilder sql = new StringBuilder();
		for (ColumnDefine column : table.columns) {
			if (column.isVersion()) {
				sql.append("1").append(SPLIT);
			} else {
				sql.append(HASH_LEFT_BRACE).append(column.javaPropertyEl).append(RIGHT_BRACE).append(SPLIT);
			}
		}
		if (table.define.useLogicDel()) {
			sql.append(HASH_LEFT_BRACE).append(delAtProperty).append(RIGHT_BRACE);
		} else {
			sql.delete(sql.lastIndexOf(SPLIT), sql.length() - 1);
		}
		return sql.toString();
	}

	/**
	 * 解析修改列
	 */
	protected String parseUpdateProperty() {
		StringBuilder sql = new StringBuilder();
		for (ColumnDefine column : this.table.columns) {

			// 开启 stat ： 增量添加的功能
			if (!column.isPk() && !column.isCreateDate() && column.isStat()) {
				sql.append("<if test=\"").append(column.javaProperty).append(" != null\">").append(column.name)
						.append(EQUALS).append(StringUtils.format(STAT_CHECK, column.name, column.name)).append(PLUS)
						.append(HASH_LEFT_BRACE).append(column.javaPropertyEl).append(RIGHT_BRACE).append(SPLIT)
						.append("</if>");
			}

			// 开启 toggle ：将需要设置的字段设置为 0 或者 1
			else if (!column.isPk() && !column.isCreateDate() && column.isToggle()) {//
				sql.append("<if test=\"").append(column.javaProperty).append(" != null\">").append(column.name)
						.append(EQUALS).append(StringUtils.format(TOGGLE_CHECK, column.name, column.name)).append(SPLIT)
						.append("</if>");
			}

			// 开启 max ：取大值
			else if (!column.isPk() && !column.isCreateDate() && column.isMax()) {//
				sql.append("<if test=\"").append(column.javaProperty).append(" != null\">").append(column.name)
						.append(EQUALS).append(StringUtils.format(MAX_CHECK, column.name, column.name,
								column.javaPropertyEl, column.name, column.javaPropertyEl))
						.append(SPLIT).append("</if>");
			}

			// 开启 min ：取小值
			else if (!column.isPk() && !column.isCreateDate() && column.isMin()) {//
				sql.append("<if test=\"").append(column.javaProperty).append(" != null\">").append(column.name)
						.append(EQUALS).append(StringUtils.format(MIN_CHECK, column.name, column.name,
								column.javaPropertyEl, column.name, column.javaPropertyEl))
						.append(SPLIT).append("</if>");
			}

			// 其他字段 - 非版本
			else if (!column.isPk() && !column.isCreateDate() && !column.isVersion()) {
				sql.append("<if test=\"").append(column.javaProperty).append(" != null\">").append(column.name)
						.append(EQUALS).append(HASH_LEFT_BRACE).append(column.javaPropertyEl).append(RIGHT_BRACE)
						.append(SPLIT).append("</if>");
			}
		}

		// 添加这段代码是为了避免校验校验之前的,
		sql.append(PADDING2);

		// 添加乐观锁的校验
		if (this.table.define.useOptimismLock()) {
			sql.append(SPLIT).append(OP_LOCK_ADD);
		}
		return sql.toString();
	}
}
